package com.wy2.generator;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Map;

import cn.xo68.core.util.StringTools;
import com.wy2.generator.exception.GeneratorInitException;
import freemarker.cache.StringTemplateLoader;
import freemarker.core.ParseException;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.MalformedTemplateNameException;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import freemarker.template.TemplateNotFoundException;

/**
 * 字符串生成器
 * @author nnsword
 * @date 2018年1月7日下午8:13:35
 *
 */
public class StringGenerator {
    
    /**
     * 得到字符串合并结果
     * @param templateEncoding
     * @param template
     * @param data
     * @return
     * @throws TemplateNotFoundException
     * @throws MalformedTemplateNameException
     * @throws ParseException
     * @throws IOException
     * @throws TemplateException
     */
    public static String generateString(String templateEncoding,StringTemplate template,Map<String,Object> data) throws Exception {
        StringGenerator stringGenerator=new StringGenerator(templateEncoding);
        stringGenerator.initTemplateConfig(template);
        String result=stringGenerator.getStringResult(template.getName(), data);
        return result;
    }

    /**
     * 模板编码
     */
    private final String templateEncoding;
    /**
     * freemarker模板配置
     */
    private Configuration templateConfiguration;
    
    
    
    
    
    public String getTemplateEncoding() {
        return templateEncoding;
    }

    public Configuration getTemplateConfiguration() {
        return templateConfiguration;
    }

    public void setTemplateConfiguration(Configuration templateConfiguration) {
        this.templateConfiguration = templateConfiguration;
    }





    public StringGenerator(String templateEncoding) {
        super();
        this.templateEncoding = templateEncoding;
    }

    /**
     * 初始化模板配置，并加载自定义标签的字符串模板
     * @date 2017-12-17 22:40:14
     * @param stringTemplates
     * @throws GeneratorInitException
     */
    public void initTemplateConfig(StringTemplate...templates) {
        templateConfiguration = new Configuration(Configuration.VERSION_2_3_22);
        StringTemplateLoader stringLoader = new StringTemplateLoader();
        for (StringTemplate template : templates) {
            stringLoader.putTemplate(template.getName(),template.getContent()); 
        }
        templateConfiguration.setTemplateLoader(stringLoader);
        
        templateConfiguration.setObjectWrapper(new DefaultObjectWrapper(Configuration.VERSION_2_3_22));
        templateConfiguration.setDefaultEncoding(this.templateEncoding);
        //设计异常处理器  
        //templateConfiguration.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
        templateConfiguration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
    }
    
    /**
     * 得到字符串合并结果
     * @param templateName
     * @param data
     * @return
     * @throws TemplateNotFoundException
     * @throws MalformedTemplateNameException
     * @throws ParseException
     * @throws IOException
     * @throws TemplateException
     */
    public String getStringResult(String templateName,Map<String,Object> data) throws Exception {
        if(StringTools.isEmpty(templateName) || data==null ) {
            return StringTools.EMPTY;
        }
        Template temp = templateConfiguration.getTemplate(templateName, this.templateEncoding);
        ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
        Writer out= new OutputStreamWriter(outputStream, this.templateEncoding);
        temp.process(data, out);
        String str = new String(outputStream.toByteArray(), this.templateEncoding);
        outputStream.close();
        out.close();
        return str;
    }
}
